
#include "inc_test.h"

#define TEST_NR	 (100000)
	
CROUT_STRUCT *crs[TEST_NR];
static void *rout(void *arg){
	unsigned long nr = (unsigned long)arg;
	// printf("[%ld]rout\n", nr);
	CROUT_STRUCT *p = atm_ld(&crs[nr]);

	CROUT_YIELD(p);
	// printf("[%ld]yield back to rout\n", nr);

	CROUT_YIELD(p);
	
	return (void *)nr;
}

void test_torture(){
	CROUT_ATTR test_attr;
	test_attr.share_stack = NULL;
	struct timespec ts;
	struct timespec dt;
	word_t cycles0;
	word_t cycles1;
	TIME_STAMP(&ts);
	for(unsigned long idx = 0; idx < TEST_NR; idx++){
			
		test_attr.stack_size = __hash64(ts.tv_nsec + idx) % MAX_STACKSIZE + MIN_STACKSIZE;
		if (0 != CROUT_CREATE(&crs[idx], &test_attr, rout, (void *)idx)){
			printf("create failed\n");
			return;
		}
	}

	TIME_STAMP(&ts);
	cycles0 = rdcnt_relax();
	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		CROUT_RESUME(crs[idx]);
	}

	shuffle((word_t *)crs, TEST_NR, ts.tv_nsec, 2023);
	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		CROUT_RESUME(crs[idx]);
	}

	shuffle((word_t *)crs, TEST_NR, ts.tv_nsec, 2023);
	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		CROUT_RESUME(crs[idx]);
	}

	cycles1 = rdcnt_relax();
	TIME_STAMP(&dt);
	printf("[%8llu ns/ops] %lu cos tortune time [us] %llu[%lld cycles/op]\n", TIME_DELTA_NS(&ts, &dt)/TEST_NR, \
			(unsigned long)TEST_NR, TIME_DELTA_US(&ts, &dt), (llong_t)(cycles1-cycles0)/TEST_NR);
	

	for(unsigned long idx = 0; idx < TEST_NR; idx++){
		CROUT_RELEASE(crs[idx]);
	}
	fprintf(stderr, "%llu\n", TIME_DELTA_US(&ts, &dt));
}

int main(){
	test_torture();
}
